﻿using System;
using System.Configuration;
using System.IO;
using System.Xml;
using vJine.Core.IO.Xml;
using vJine.Core.IoC;
using vJine.Core.ORM;

namespace vJine.Core {
    /// <summary>
    /// 应用程序配置特性
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class AppConfigAttribute : Attribute {
        private AppConfigAttribute() {
        }
        /// <summary>
        /// 实例化应用程序配置特性
        /// </summary>
        /// <param name="sectionName">配置节名称</param>
        public AppConfigAttribute(string sectionName) {
            this.sectionName = sectionName;
        }
        /// <summary>
        /// 配置节名称
        /// </summary>
        public string sectionName { get; protected set; }
    }

    /// <summary>
    /// 配置文件操作类
    /// </summary>
    /// <typeparam name="Tconfig">配置实体类型</typeparam>
    public class AppConfig<Tconfig> : IConfigurationSectionHandler where Tconfig : class, new() {
        /// <summary>
        /// 实例化配置文件操作类
        /// </summary>
        internal AppConfig() {
        }
        /// <summary>
        /// 反序列化应用程序配置文件配置节
        /// </summary>
        /// <param name="parent">上级节点</param>
        /// <param name="configContext">配置上下文</param>
        /// <param name="section">配置节XML节点</param>
        /// <returns>配置类实体实例</returns>
        public object Create(object parent, object configContext, XmlNode section) {
            return XmlHelper.Parse<Tconfig>(section);
        }

        static readonly string _AssemblyQualifiedName;
        /// <summary>
        /// 配置类实体完全限定名
        /// </summary>
        public static string AssemblyQualifiedName {
            get {
                return AppConfig<Tconfig>._AssemblyQualifiedName;
            }
        }

        static readonly string _FullName;
        /// <summary>
        /// 配置类实体全名
        /// </summary>
        public static string FullName {
            get {
                return AppConfig<Tconfig>._FullName;
            }
        }

        static readonly string sectionName = null;
        static AppConfig() {
            AppConfig<Tconfig>._AssemblyQualifiedName = Class<AppConfig<Tconfig>>.AssemblyQualifiedName; ;
            AppConfig<Tconfig>._FullName = Class<AppConfig<Tconfig>>.FullName;

            Type typeConfig = typeof(Tconfig);
            AppConfigAttribute[] appConfigs = Reflect.GetAttribute<AppConfigAttribute>(typeConfig);
            if (appConfigs == null || appConfigs.Length == 0) {
                AppConfig<Tconfig>.sectionName = null;
            } else {
                AppConfig<Tconfig>.sectionName = appConfigs[0].sectionName;
            }
        }

        /// <summary>
        /// 从程序配置文件中读取配置类实体值(配置节名称需由AppConfigAttribute指定)
        /// </summary>
        /// <returns>配置类实体</returns>
        public static Tconfig Get() {
            string sectionName = AppConfig<Tconfig>.sectionName;
            if (string.IsNullOrEmpty(sectionName)) {
                throw new CoreException("未指定配置节名称，实体类型:[{0}]", Class<Tconfig>.FullName);
            }

            return AppConfig<Tconfig>.Get(sectionName) as Tconfig;
        }

        /// <summary>
        /// 从程序配置文件中读取配置类实体值
        /// </summary>
        /// <param name="section_name">配置节名称</param>
        /// <returns>配置类实体</returns>
        public static Tconfig Get(string section_name) {
            return ConfigurationManager.GetSection(section_name) as Tconfig; 
        }

        /// <summary>
        /// 从指定的配置文件中加载配置类实体
        /// </summary>
        /// <param name="config_file">配置文件</param>
        /// <returns>配置类实体</returns>
        public static Tconfig Load(string config_file) {
            return vJine.Core.IO.Xml.XmlHelper.Parse<Tconfig>(config_file);
        }

        /// <summary>
        /// 将配置类实体保存到指定的配置文件中
        /// </summary>
        /// <param name="config">配置类实体</param>
        /// <param name="config_file">配置文件</param>
        public static void Save(Tconfig config, string config_file) {
            vJine.Core.IO.Xml.XmlHelper.ToString<Tconfig>(config, config_file);
        }
    }
}
